package com.healthcloud.shiro;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

import org.apache.shiro.cache.CacheException;

import com.healthcloud.cache.ExpirationCache;
import com.healthcloud.exception.MethodNotSupportException;

/**
 * 适配器, 将 spring {@link org.springframework.cache.Cache} 的缓存功能适配到 shiro 的 {@link org.apache.shiro.cache.Cache}
 *
 * Created by xiam on 2015/6/6.
 */
public class SpringCacheAdapter<K, T> implements ExpiredCache<K, T> {

	private boolean throwMethodNotSupportedException = true;

	private org.springframework.cache.Cache cache;

	private boolean supportedExpired = false;

	public SpringCacheAdapter(boolean throwMethodNotSupportedException,
			org.springframework.cache.Cache cache) {
		this.throwMethodNotSupportedException = throwMethodNotSupportedException;
		this.cache = cache;
		if (cache instanceof ExpirationCache) {
			supportedExpired = true;
		}
	}

	@Override
	public T get(K key) throws CacheException {
		org.springframework.cache.Cache.ValueWrapper valueWrapper = cache.get(key);
		if (valueWrapper == null) {
			return null;
		}
		return (T) valueWrapper.get();
	}

	@Override
	public T put(K key, T value) throws CacheException {
		T previous = this.get(key);
		cache.put(key, value);
		return previous;
	}

	@Override
	public T remove(K key) throws CacheException {
		T previous = this.get(key);
		cache.evict(key);
		return previous;
	}

	@Override
	public void clear() throws CacheException {
		cache.clear();
	}

	@Override
	public int size() {
		if (throwMethodNotSupportedException) {
			throw new MethodNotSupportException("Method public int size() is not supported.");
		}
		return 0;
	}

	@Override
	public Set<K> keys() {
		if (throwMethodNotSupportedException) {
			throw new MethodNotSupportException("Method public Set<K> keys() is not supported.");
		}
		return Collections.emptySet();
	}

	@Override
	public Collection<T> values() {
		if (throwMethodNotSupportedException) {
			throw new MethodNotSupportException(
					"Method public Collection<T> values() is not supported.");
		}
		return Collections.emptyList();
	}

	@Override
	public T put(K key, T value, long expired) throws CacheException {
		if (supportedExpired) {
			T previous = this.get(key);
			((ExpirationCache) cache).put(key, value, expired);
			return previous;
		}
		throw new CacheException("Expiration not supported.");
	}
}
